package se.statifyme.server.declaration;

import java.util.Date;
import java.util.List;

import javax.persistence.Basic;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlRootElement;

import se.statifyme.shared.StringUtils;

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class ItemDeclaration {
	
	public enum SupportedType {
		STRING(String.class),
		DATE(Date.class),
		BOOLEAN(Boolean.class),
		BOOLEAN_PRIMITIVE(boolean.class),
		DOUBLE(Double.class),
		DOUBLE_PRIMITIVE(double.class),
		LONG(Long.class),
		LONG_PRIMITIVE(long.class),
		INTEGER(Integer.class),
		INTEGER_PRIMITIVE(int.class),
		SHORT(Short.class),
		SHORT_PRIMITIVE(short.class),
		CHARACTER(Character.class),
		CHARACTER_PRIMITIVE(char.class),
		;
		private final Class<?> clazz;
		private SupportedType(Class<?> clazz) {
			this.clazz = clazz;
		}
		
		public static boolean isSupported(Class<?> clazz) {
			return isSupported(clazz.getName());
		}
		
		public static boolean isSupported(String clazz) {
			for (SupportedType type : values()) {
				if (type.clazz.getName().equals(clazz)) {
					return true;
				}
			}
			return false;
		}
	}

	@Basic(optional = false)
	private String displayName;
	
	@Basic(optional = false)
	private List<Field> fields;

	public String getDisplayName() {
		return displayName;
	}

	public void setDisplayName(String displayName) {
		this.displayName = displayName;
	}

	public List<Field> getFields() {
		return fields;
	}

	public void setFields(List<Field> fields) {
		this.fields = fields;
	}

	@XmlRootElement
	@XmlAccessorType(XmlAccessType.FIELD)
	public static final class Field {

		@Basic(optional = false)
		private String id;
		@Basic(optional = false)
		private String type;
		
		private String displayName;
		private boolean internal;
		private boolean idField;
		private boolean optional;
		
		public Field() {
		}

		public Field(String id, String type) {
			if (StringUtils.isBlank(id)) {
				throw new IllegalArgumentException("Field ID must not be blank");
			}
			if (StringUtils.isBlank(type)) {
				throw new IllegalArgumentException("Field type must not be blank");
			} else if (!SupportedType.isSupported(type)) {
				throw new IllegalArgumentException("Type '" + type + "' not supported");
			}
			this.id = id;
			this.type = type;
		}
		
		public boolean isInternal() {
			return internal;
		}

		public void setInternal(boolean internal) {
			this.internal = internal;
		}

		public boolean isOptional() {
			return optional;
		}

		public void setOptional(boolean optional) {
			this.optional = optional;
		}

		public String getId() {
			return id;
		}

		public String getType() {
			return type;
		}

		public String getDisplayName() {
			return displayName;
		}

		public void setDisplayName(String displayName) {
			this.displayName = displayName;
		}

		public boolean isIdField() {
			return idField;
		}

		public void setIdField(boolean idField) {
			this.idField = idField;
		}
	}
}
